/*
 * @Author: your name
 * @Date: 2021-01-28 11:26:09
 * @LastEditTime: 2021-04-16 17:12:21
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \tower_defense\assets\scripts\game_scene\tower\warlock_bullet.ts
 */

import { UG } from "../../modules/ugame"
import { WarlockBulletParams } from "../../game_data/tower_data/warlock_bullet_params";
import Enemy from "../enemy/enemy";
import { FrameAnim } from "../../common/frame_anim";

const { ccclass, property } = cc._decorator;

// 自定义类
@ccclass("warlock_bullet_skin")
class warlock_bullet_skin {
    @property(cc.SpriteFrame)   // 子弹图片
    public warlock_bullet_icon: cc.SpriteFrame = null;
}

@ccclass
export class WarlockBullet extends cc.Component {

    @property(cc.Integer)   // 子弹移动速度
    public speed: number = 200;

    @property(cc.Integer)   // 子弹攻击力
    public attack: number = 10;

    @property(cc.Integer)  // 子弹等级
    public bullet_level: number = 1;

    @property(cc.Node)          // 子弹精灵节点
    public anim_node: cc.Node = null;

    @property(cc.Integer)
    public bullet_effect_sample: number = 10;    // 子弹效果帧速率

    @property(cc.SpriteFrame)   // 子弹效果资源
    public bullet_effect_anim: Array<cc.SpriteFrame> = [];

    @property({
        type: warlock_bullet_skin,
    })
    public level_bullet_skin = [];   // 每个等级子弹皮肤

    public bullet_root_node: cc.Node = null;    // 子弹存放节点
    public shoot_enemy: cc.Node = null;         // 敌人

    public warlock_bullet_frame_anim: FrameAnim = null;    // 保存自定义动画组件

    onLoad() {
        this.bullet_root_node = cc.find('Canvas/tower_panel/bullet_root');
        this._set_bullet_skin_by_level();

        // 绑定自定义动画组件
        this.warlock_bullet_frame_anim = this.anim_node.addComponent(FrameAnim);
        this.warlock_bullet_frame_anim.sprite_com = this.anim_node.getComponent(cc.Sprite);
        this.warlock_bullet_frame_anim.anim_com = this.anim_node.getComponent(cc.Animation);
    }

    // 设置子弹皮肤
    private _set_bullet_skin_by_level(): void {
        this.anim_node.getComponent(cc.Sprite).spriteFrame = this.level_bullet_skin[this.bullet_level - 1].warlock_bullet_icon;
    }

    // 子弹射击
    public shoot(level: number, bullet_world_pos: cc.Vec2, enemy_world_pos: cc.Vec2, enemy: cc.Node): void {
        // 
        this.warlock_bullet_frame_anim.sprite_frame_arr = this.bullet_effect_anim;
        this.warlock_bullet_frame_anim.sample = this.bullet_effect_sample;

        // 子弹参数
        this.bullet_level = level;
        this.speed = WarlockBulletParams[this.bullet_level - 1].speed;
        this.attack = WarlockBulletParams[this.bullet_level - 1].attack;
        this.shoot_enemy = enemy;

        this._set_bullet_skin_by_level();

        // 把敌人，转换成和子弹同一个坐标系下
        let start_pos: cc.Vec2 = this.bullet_root_node.parent.convertToNodeSpaceAR(bullet_world_pos);
        let end_pos: cc.Vec2 = this.bullet_root_node.parent.convertToNodeSpaceAR(enemy_world_pos);

        // 调整位置
        this.node.setPosition(start_pos);

        let dir: cc.Vec2 = enemy_world_pos.sub(bullet_world_pos);   // 移动方向
        let len: number = dir.mag();                    // 向量差长度
        let time: number = len / this.speed;            // 求运动时间

        if (this.shoot_enemy) {
            let enemy_com: Enemy = this.shoot_enemy.getComponent(Enemy);
            end_pos = enemy_com.walk_pos_by_time(time);
        }

        // 平移运动
        cc.tween(this.node)
            .to(time, { x: end_pos.x, y: end_pos.y })
            .call(() => {
                // 执行爆炸动画、伤害计算
                this._bullet_boom_anim();
                // 伤害计算
                this._on_bullet_shoot_enemy();
            })
            .start();

    }

    // 爆炸动画
    private _bullet_boom_anim(): void {
        this.warlock_bullet_frame_anim.sprite_frame_arr = this.bullet_effect_anim;
        this.warlock_bullet_frame_anim.sample = this.bullet_effect_sample;

        // 播放一次爆炸动画
        this.warlock_bullet_frame_anim.play_once(() => {
            // 移除子弹
            this.node.destroy();
        });
    }

    // 子弹伤害 --> 单点伤害
    private _on_bullet_shoot_enemy(): void {
        if (!this.shoot_enemy || !UG.is_enemy_active(this.shoot_enemy)) {
            return;
        }

        // 击中怪物
        let enemy: Enemy = this.shoot_enemy.getComponent(Enemy);
        enemy.on_warlock_attacked(WarlockBulletParams[this.bullet_level - 1].attack);
    }

}
